/**
 * 
 */
package org.mediahouse.trac.model;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @author Tin
 * @version %I%, %G%
 * 
 */
public abstract class AbstractItem implements Item {

    private static final Locale LOCALE = Locale.getDefault();
    protected final Map<String, Object> info;
    protected String uid;

    /**
     * If this constructor is overridden, the {@link #uid} field <em>must</em>
     * be explicitly set by the overriding class.
     */
    protected AbstractItem() {
        this(string.empty);
    }

    /**
     * Constructs a new instance of {@code AbstractItem} with a user-specified
     * UID.
     * 
     * @param uid
     *            the string to use as this item's UID
     */
    public AbstractItem(final String uid) {
        this.uid = uid;
        this.info = new HashMap<String, Object>();
        this.info.put("uid", uid);
    }

    /**
     * {@inheritDoc}
     * 
     * @see {@linkplain com.mediahouse.trac.model.Item#getProperty(String)}
     */
    @Override
    public final Object getProperty(final String field) {
        if (!this.info.containsKey(field)) return null;
        else {
            final Object info = this.info.get(field.toLowerCase(LOCALE));
            return (info == null) ? null : info;
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see {@linkplain com.mediahouse.trac.model.Item#hasProperty(String)}
     */
    @Override
    public final boolean hasProperty(final String field) {
        return info.containsKey(field.toLowerCase(LOCALE));
    }

    /**
     * {@inheritDoc}
     * 
     * @see {@linkplain com.mediahouse.trac.model.Item#setProperty(String, Object)}
     */
    @Override
    public Item setProperty(final String field, final Object value) {
        final String property = field.toLowerCase(LOCALE);

        if (field == null || value == null) return this;
        if (isAccessPrevented(property)) throw new IllegalArgumentException("Cannot modify the property: ".concat(property));
        else this.info.put(property, value);
        return this;
    }

    protected boolean isAccessPrevented(final String property) {
        if (property.equalsIgnoreCase("uid")) return true;
        else return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see {@linkplain com.mediahouse.trac.model.Item#uid()}
     */
    @Override
    public final String uid() {
        return uid;
    }

    /**
     * @author Tin
     * @version %I%, %G%
     */
    private static final class string {

        public static final String empty = "";

    }
}
